package com.zhuo.project.order.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

import com.zhuo.common.enums.IsSendStatus;
import com.zhuo.common.enums.SendStatus;
import com.zhuo.common.utils.DateUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.zhuo.common.utils.SecurityUtils;
import com.zhuo.framework.redis.RedisCache;
import com.zhuo.project.hms.domain.ZzClinicRefDepot;
import com.zhuo.project.hms.service.IZzClinicRefDepotService;
import com.zhuo.project.k3.domain.ZzDepot;
import com.zhuo.project.k3.service.IZzDepotService;
import com.zhuo.project.order.domain.ZzDiagnoseDetail;
import com.zhuo.project.order.domain.ZzDiagnoseHead;
import com.zhuo.project.order.domain.ZzTask;
import com.zhuo.project.order.dto.k3.AccessResult;
import com.zhuo.project.order.dto.k3.FEntity;
import com.zhuo.project.order.dto.k3.FEntityDto;
import com.zhuo.project.order.dto.k3.SendDeliveryInfo;
import com.zhuo.project.order.dto.k3.SendK3Dto;
import com.zhuo.project.order.dto.k3.SendK3Info;
import com.zhuo.project.order.mapper.ZzDiagnoseSendMapper;
import com.zhuo.project.order.domain.ZzDiagnoseSend;
import com.zhuo.project.order.service.IZzDiagnoseDetailService;
import com.zhuo.project.order.service.IZzDiagnoseHeadService;
import com.zhuo.project.order.service.IZzDiagnoseSendService;
import com.zhuo.project.order.service.IZzTaskService;
import com.zhuo.project.order.service.task.K3Service;
import com.zhuo.project.system.domain.SysUser;
import com.zhuo.project.system.service.ISysUserService;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;

/**
 * 处方单发药明细Service业务层处理
 *
 * @author zhuo
 * @date 2020-03-26
 */
@Service
public class ZzDiagnoseSendServiceImpl implements IZzDiagnoseSendService {
    private static Logger logger = LoggerFactory.getLogger(ZzDiagnoseSendServiceImpl.class);
    @Autowired
    private ZzDiagnoseSendMapper zzDiagnoseSendMapper;

    @Autowired
    private IZzDiagnoseHeadService iZzDiagnoseHeadService;

    @Autowired
    private IZzDiagnoseDetailService iZzDiagnoseDetailService;

    @Autowired
    private IZzTaskService iZzTaskService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ISysUserService iSysUserService;

    @Autowired
    private K3Service k3Service;

    @Autowired
    private IZzDepotService iZzDepotService;

    @Autowired
    private IZzClinicRefDepotService iZzClinicRefDepotService;

    /**
     * 查询处方单发药明细
     *
     * @param id 处方单发药明细ID
     * @return 处方单发药明细
     */
    @Override
    public ZzDiagnoseSend selectZzDiagnoseSendById(Long id) {
        return zzDiagnoseSendMapper.selectZzDiagnoseSendById(id);
    }

    @Override
    public ZzDiagnoseSend selectZzDiagnoseSendByItemNo(String sendId, Integer itemNo, String materialId) {
        ZzDiagnoseSend zzDiagnoseSend = new ZzDiagnoseSend();
        zzDiagnoseSend.setSendId(sendId);
        zzDiagnoseSend.setItemNo(itemNo);
        zzDiagnoseSend.setMaterialId(materialId);
        List<ZzDiagnoseSend> retList = zzDiagnoseSendMapper.selectZzDiagnoseSendList(zzDiagnoseSend);
        return retList.get(0);
    }

    @Override
    public List<ZzDiagnoseSend> selectZzDiagnoseSendBySendId(String sendId) {
        return zzDiagnoseSendMapper.selectZzDiagnoseSendBySendId(sendId);
    }


    public Map<String, Double> getSendQtyMap(String sendId) {
        List<ZzDiagnoseSend> zzDiagnoseSendList = selectZzDiagnoseSendBySendId(sendId);
        /* 新增配药数据 */
        Map<String, Double> sendQtyMap = new HashMap<>(zzDiagnoseSendList.size());
        for (ZzDiagnoseSend zzDiagnoseSend : zzDiagnoseSendList) {
            if (sendQtyMap.containsKey(zzDiagnoseSend.getMaterialId())) {
                sendQtyMap.put(zzDiagnoseSend.getMaterialId(),
                        sendQtyMap.get(zzDiagnoseSend.getMaterialId() + zzDiagnoseSend.getSendQty()));
            } else {
                sendQtyMap.put(zzDiagnoseSend.getMaterialId(), zzDiagnoseSend.getSendQty());
            }
        }
        return sendQtyMap;
    }

    public int isEquipOrSend(String sendId) {
        List<ZzDiagnoseSend> zzDiagnoseSendList = selectZzDiagnoseSendBySendId(sendId);
        /* 新增配药数据 */
        Map<String, Double> equitQtyMap = new HashMap<>(zzDiagnoseSendList.size());
        for (ZzDiagnoseSend zzDiagnoseSend : zzDiagnoseSendList) {
            if (equitQtyMap.containsKey(zzDiagnoseSend.getMaterialId())) {
                equitQtyMap.put(zzDiagnoseSend.getMaterialId(),
                        equitQtyMap.get(zzDiagnoseSend.getMaterialId() + zzDiagnoseSend.getSendQty()));
            } else {
                equitQtyMap.put(zzDiagnoseSend.getMaterialId(), zzDiagnoseSend.getSendQty());
            }
        }
        /* 更新处方单状态 */

        Integer isEquipOrSend = 0;
        Map<String, Double> leftQtyMap =
                iZzDiagnoseDetailService.getDiagnoseLeftQty(zzDiagnoseSendList.get(0).getDiagnoseId());
        Iterator<Entry<String, Double>> entries = leftQtyMap.entrySet().iterator();
        while (entries.hasNext()) {
            Entry<String, Double> entry = entries.next();
            String materialId = entry.getKey();
            Double leftQty = entry.getValue();
            if (leftQty < 0) {
                isEquipOrSend = IsSendStatus.SEND_OVER.getCode();
                break;
            }

            if (!equitQtyMap.containsKey(materialId) && leftQty > 0) {
                isEquipOrSend = IsSendStatus.SEND_PART.getCode();
                break;
            }

            if (leftQty.compareTo(0.0) == 0 && !equitQtyMap.containsKey(materialId)) {
                continue;
            }

            if (leftQty.compareTo(equitQtyMap.get(materialId)) == 0) {
                isEquipOrSend = IsSendStatus.SEND_DONE.getCode();
            } else if (leftQty.compareTo(equitQtyMap.get(materialId)) > 0) {
                isEquipOrSend = IsSendStatus.SEND_PART.getCode();
                break;
            } else {
                isEquipOrSend = IsSendStatus.SEND_OVER.getCode();
                break;
            }
        }
        return isEquipOrSend;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchUpdate(List<ZzDiagnoseSend> list) {
        ZzDiagnoseSend zzDiagnoseSendFirst = list.get(0);

        ZzDiagnoseHead zzDiagnoseHead =
                iZzDiagnoseHeadService.selectZzDiagnoseHeadByDiagnoseId(zzDiagnoseSendFirst.getDiagnoseId());
        Long id = zzDiagnoseHead.getId();
        ZzDiagnoseHead updateDiagnoseHead = new ZzDiagnoseHead();
        updateDiagnoseHead.setId(id);
        updateDiagnoseHead.setIsEquip(isEquipOrSend(zzDiagnoseSendFirst.getSendId()));
        updateDiagnoseHead.setIsSend(isEquipOrSend(zzDiagnoseSendFirst.getSendId()));
        iZzDiagnoseHeadService.updateZzDiagnoseHead(updateDiagnoseHead);

        // 获取配药数量
        Map<String, Double> sendQtyMap = getSendQtyMap(zzDiagnoseSendFirst.getSendId());
        List<ZzDiagnoseDetail> zzDiagnoseDetailList =
                iZzDiagnoseDetailService.selectZzDiagnoseDetailByDiagnoseId(zzDiagnoseSendFirst.getDiagnoseId());
        for (ZzDiagnoseDetail detail : zzDiagnoseDetailList) {
            String materialId = detail.getMaterialId();
            if (sendQtyMap.containsKey(materialId)) {
                double leftQty = detail.getQty() - detail.getTotalSendQty();
                if (leftQty > 0) {
                    // 还有剩余药物未发
                    ZzDiagnoseDetail updateDetail = new ZzDiagnoseDetail();
                    updateDetail.setId(detail.getId());
                    double itemSendQty = detail.getTotalSendQty() + (sendQtyMap.get(materialId) <= leftQty ? sendQtyMap
                            .get(materialId) : leftQty);
                    updateDetail.setTotalSendQty(itemSendQty);
                    iZzDiagnoseDetailService.updateZzDiagnoseDetail(updateDetail);
                }
            }
        }

        for (ZzDiagnoseSend zzDiagnoseSend : list) {
            zzDiagnoseSendMapper.updateZzDiagnoseSend(zzDiagnoseSend);
        }
        ZzTask zzTask = new ZzTask();
        zzTask.setType(40);
        zzTask.setRefId(zzDiagnoseSendFirst.getSendId());
        zzTask.setStatus(0);
        zzTask.setContent(zzDiagnoseHead.getEncounterId());
        zzTask.setValid(1);
        zzTask.setExecCount(0);
        zzTask.setRemark("");
        zzTask.setCreateTime(new Date());
        iZzTaskService.insertZzTask(zzTask);
        return list.size();
    }

    /**
     * 查询处方单发药明细列表
     *
     * @param zzDiagnoseSend 处方单发药明细
     * @return 处方单发药明细
     */
    @Override
    public List<ZzDiagnoseSend> selectZzDiagnoseSendList(ZzDiagnoseSend zzDiagnoseSend) {
        return zzDiagnoseSendMapper.selectZzDiagnoseSendList(zzDiagnoseSend);
    }

    @Override
    public List<ZzDiagnoseSend> selectZzDiagnoseSendListByDiagnoseId(String diagnoseId) {
        return zzDiagnoseSendMapper.selectZzDiagnoseSendListByDiagnoseId(diagnoseId);
    }

    /**
     * 新增处方单发药明细
     *
     * @param zzDiagnoseSend 处方单发药明细
     * @return 结果
     */
    @Override
    public int insertZzDiagnoseSend(ZzDiagnoseSend zzDiagnoseSend) {
        zzDiagnoseSend.setCreateTime(DateUtils.getNowDate());
        return zzDiagnoseSendMapper.insertZzDiagnoseSend(zzDiagnoseSend);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteBySendId(String sendId) {
        ZzDiagnoseSend zzDiagnoseSendSearch = new ZzDiagnoseSend();
        zzDiagnoseSendSearch.setSendId(sendId);
        zzDiagnoseSendSearch.setSendStatus(SendStatus.EQUIP.getCode());
        zzDiagnoseSendSearch.setEquipBy(SecurityUtils.getUsername());
        List<ZzDiagnoseSend> zzDiagnoseSendListSearch =
                this.selectZzDiagnoseSendList(zzDiagnoseSendSearch);
        if (null != zzDiagnoseSendListSearch && zzDiagnoseSendListSearch.size() > 0) {
            List<Long> ids = zzDiagnoseSendListSearch.stream().map(bo -> bo.getId()).collect(Collectors.toList());
            this.deleteZzDiagnoseSendByIds(ids.toArray(new Long[ids.size()]));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchInsertZzDiagnoseSend(List<ZzDiagnoseSend> zzDiagnoseSendList) {
         /*
          删除当前人之前操作的配药数据，然后insert
         */
        ZzDiagnoseSend zzDiagnoseSendFirst = zzDiagnoseSendList.get(0);
        ZzDiagnoseSend zzDiagnoseSendSearch = new ZzDiagnoseSend();
        zzDiagnoseSendSearch.setDiagnoseId(zzDiagnoseSendFirst.getDiagnoseId());
        zzDiagnoseSendSearch.setSendStatus(SendStatus.EQUIP.getCode());
        zzDiagnoseSendSearch.setEquipBy(SecurityUtils.getUsername());
        List<ZzDiagnoseSend> zzDiagnoseSendListSearch =
                this.selectZzDiagnoseSendList(zzDiagnoseSendSearch);
        if (null != zzDiagnoseSendListSearch && zzDiagnoseSendListSearch.size() > 0) {
            List<Long> ids = zzDiagnoseSendListSearch.stream().map(bo -> bo.getId()).collect(Collectors.toList());
            this.deleteZzDiagnoseSendByIds(ids.toArray(new Long[ids.size()]));
        }

        /* 新增配药数据  */
        for (ZzDiagnoseSend zzDiagnoseSend : zzDiagnoseSendList) {
            zzDiagnoseSendMapper.insertZzDiagnoseSend(zzDiagnoseSend);
        }
        /*更新处方单状态 */
        ZzDiagnoseHead zzDiagnoseHead =
                iZzDiagnoseHeadService.selectZzDiagnoseHeadByDiagnoseId(zzDiagnoseSendFirst.getDiagnoseId());
        Long id = zzDiagnoseHead.getId();
        ZzDiagnoseHead updateDiagnoseHead = new ZzDiagnoseHead();
        updateDiagnoseHead.setId(id);
        updateDiagnoseHead.setIsEquip(isEquipOrSend(zzDiagnoseSendFirst.getSendId()));
        iZzDiagnoseHeadService.updateZzDiagnoseHead(updateDiagnoseHead);

        return zzDiagnoseSendList.size();
    }


    /**
     * 修改处方单发药明细
     *
     * @param zzDiagnoseSend 处方单发药明细
     * @return 结果
     */
    @Override
    public int updateZzDiagnoseSend(ZzDiagnoseSend zzDiagnoseSend) {
        zzDiagnoseSend.setUpdateTime(DateUtils.getNowDate());
        return zzDiagnoseSendMapper.updateZzDiagnoseSend(zzDiagnoseSend);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sendDelivery2K3(ZzTask zzTask) throws Exception {
        SendDeliveryInfo sendDeliveryInfo = new SendDeliveryInfo();
        String token = k3Service.signIn();
        sendDeliveryInfo.setACCESSTOKEN(token);
        List<ZzDiagnoseSend> zzDiagnoseSendList = zzDiagnoseSendMapper.selectZzDiagnoseSendBySendId(zzTask.getRefId());
        ZzDiagnoseSend zzDiagnoseSendFirst = zzDiagnoseSendList.get(0);
        String fDate = DateUtil.format(zzDiagnoseSendFirst.getSendTime(), "yyyy-MM-dd");
        sendDeliveryInfo.setFDATE(fDate);
        ZzDepot zzDepot = iZzDepotService.selectZzDepotByDepotCode(zzDiagnoseSendFirst.getDepotCode());
        ZzDiagnoseHead zzDiagnoseHead =
                iZzDiagnoseHeadService.selectZzDiagnoseHeadByDiagnoseId(zzDiagnoseSendFirst.getDiagnoseId());
        ZzClinicRefDepot zzClinicRefDepot = iZzClinicRefDepotService
                .selectZzClinicRefDepotByDepotCodeAndClinicCode(zzDiagnoseSendFirst.getDepotCode(),
                        zzDiagnoseSendFirst.getDeptCode());

        sendDeliveryInfo.setFSTOCKORGID(zzDepot.getFuseorgid());
        sendDeliveryInfo.setFDeptId(zzClinicRefDepot.getDepartmentCode());
        sendDeliveryInfo.setFBILLTYPEID("QTCKD01_SYS");
        sendDeliveryInfo.setFSTOCKDIREC("GENERAL");
        List<FEntity> FEntityList = new ArrayList<>();
        List<FEntityDto> FEntityDtoList = new ArrayList<>();
        for (ZzDiagnoseSend zzDiagnoseSend : zzDiagnoseSendList) {
            FEntity fEntity = new FEntity();
            fEntity.setFMATERIALID(zzDiagnoseSend.getMaterialId());
            SysUser sysUser = iSysUserService.selectUserByUserName(zzDiagnoseSend.getSendBy());
            fEntity.setFNURSEID(sysUser.getK3Code());
            Double fqty = zzDiagnoseSend.getSendQty() * 1.0 * zzDiagnoseSend.getBaseQtyUnit();
            fEntity.setFQty(fqty.toString());
            Integer fseq = zzDiagnoseSend.getItemNo() / 10;
            fEntity.setFSEQ(fseq.toString());
            fEntity.setFSTOCKID(zzDiagnoseSend.getDepotCode());
            fEntity.setF_UN_Text6(zzDiagnoseHead.getDoctorCode());
            fEntity.setF_UN_Text2(zzDiagnoseHead.getDoctorName());
            fEntity.setF_UN_Text4(zzDiagnoseHead.getDiagnoseCode().toString());
            fEntity.setF_UN_Text5(zzDiagnoseHead.getOrderType() == 1 ? "处方单" : "商品及杂项单");
            fEntity.setF_UN_Text8(zzDiagnoseSend.getSendId());
            fEntity.setF_UN_Text9(zzDiagnoseSend.getItemNo().toString());
            FEntityList.add(fEntity);

            /**
             * k3请求接口说明内容
             */
            FEntityDto fEntityDto = new FEntityDto();
            fEntityDto.setFMATERIALID(zzDiagnoseSend.getMaterialId());
            fEntityDto.setFMATERIALIDName(zzDiagnoseSend.getMaterialName());
            fEntityDto.setFNURSEID(sysUser.getK3Code());
            fEntityDto.setFNURSEIDName(sysUser.getNickName());
            fEntityDto.setFQty(fqty.toString());
            fEntityDto.setFSEQ(fseq.toString());
            fEntityDto.setFSTOCKID(zzDiagnoseSend.getDepotCode());
            fEntityDto.setFSTOCKIDName(zzDiagnoseSend.getDepotName());
            fEntityDto.setF_UN_Text6(zzDiagnoseHead.getDoctorCode());
            fEntityDto.setF_UN_Text2(zzDiagnoseHead.getDoctorName());
            fEntityDto.setF_UN_Text4(zzDiagnoseHead.getDiagnoseCode().toString());
            fEntityDto.setF_UN_Text5(zzDiagnoseHead.getOrderType() == 1 ? "处方单" : "商品及杂项单");
            fEntityDto.setF_UN_Text8(zzDiagnoseSend.getSendId());
            fEntityDto.setF_UN_Text9(zzDiagnoseSend.getItemNo().toString());
            FEntityDtoList.add(fEntityDto);
        }
        sendDeliveryInfo.setFEntity(FEntityList);
        AccessResult accessResult = k3Service.saveMisDelivery(sendDeliveryInfo);
        if (accessResult.getCode().equals("0")) {
            zzTask.setStatus(2);
            zzTask.setUpdateTime(new Date());
            zzTask.setRemark(accessResult.getMessage());
            iZzTaskService.updateZzTask(zzTask);

            // 更新发货的状态
            for (ZzDiagnoseSend zzDiagnoseSend : zzDiagnoseSendList) {
                ZzDiagnoseSend updateSend = new ZzDiagnoseSend();
                updateSend.setId(zzDiagnoseSend.getId());
                updateSend.setUpdateTime(new Date());
                updateSend.setSendStatus(3);
                zzDiagnoseSendMapper.updateZzDiagnoseSend(updateSend);
            }
        }else {
            //  处理失败
            zzTask.setStatus(3);
            zzTask.setUpdateTime(new Date());
            zzTask.setRemark(accessResult.getMessage());
            iZzTaskService.updateZzTask(zzTask);
        }
        SendK3Dto sendK3Dto = new SendK3Dto();
        sendK3Dto.setType(zzTask.getType());
        sendK3Dto.setTypeName("发药/货");
        sendK3Dto.setReqJson(JSONUtil.toJsonPrettyStr(sendDeliveryInfo));
        sendK3Dto.setResJson(JSONUtil.toJsonPrettyStr(accessResult));
        SendK3Info sendK3Info = new SendK3Info();
        sendK3Info.setACCESSTOKEN(sendDeliveryInfo.getACCESSTOKEN());
        sendK3Info.setFDATE(sendDeliveryInfo.getFDATE());
        sendK3Info.setFDeptId(sendDeliveryInfo.getFDeptId());
        sendK3Info.setFDeptName(zzClinicRefDepot.getDepartmentName());
        sendK3Info.setFSTOCKORGID(sendDeliveryInfo.getFSTOCKORGID());
        sendK3Info.setFSTOCKORGIDName(zzDepot.getFuseorgname());
        sendK3Info.setFBILLTYPEID(sendDeliveryInfo.getFBILLTYPEID());
        sendK3Info.setFBILLTYPEIDName("销售其它出库单");
        sendK3Info.setFSTOCKDIREC(sendDeliveryInfo.getFSTOCKDIREC());
        sendK3Info.setFSTOCKDIRECName("普通");
        sendK3Info.setFEntity(FEntityDtoList);
        sendK3Dto.setData(sendK3Info);
        redisCache.setCacheObject("zhuozheng:k3:send:"+zzTask.getRefId(), JSONUtil.toJsonStr(sendK3Dto));
    }

    /**
     * 批量删除处方单发药明细
     *
     * @param ids 需要删除的处方单发药明细ID
     * @return 结果
     */
    @Override
    public int deleteZzDiagnoseSendByIds(Long[] ids) {
        return zzDiagnoseSendMapper.deleteZzDiagnoseSendByIds(ids);
    }

    /**
     * 删除处方单发药明细信息
     *
     * @param id 处方单发药明细ID
     * @return 结果
     */
    @Override
    public int deleteZzDiagnoseSendById(Long id) {
        return zzDiagnoseSendMapper.deleteZzDiagnoseSendById(id);
    }
}
